/*
    实现一个LazyMan 可以按照以下方式调用
    LazyMan('Hank');
    输出：
    Hi! This is Hank!

    LazyMan('Hank').sleep(10).eat('dinner');
    输出
    Hi! This is Hank!
    // 等待10s
    Wake up after 10
    Eat dinner~

    LazyMan('Hank').eat('dinner').eat('supper');
    输出
    Hi! This is Hank!
    Eat dinner~
    Eat supper~


    LazyMan('Hank').sleepFirst(5).eat('supper');
    输出
    // 等待5s
    Hi! This is Hank!
    Eat supper~

    // 依次类推
*/ 

/*
    1. 一个函数，打印 Hi! This is ${name}!
    2. 一个函数，打印 Eat ${type: supper || denner}~
    3. 一个sleep函数，用于等待和阻塞
    4. 一个sleepFirst函数，用于等待和阻塞
*/


class _LazyMan {
    constructor(name) {
        this.tasks = [];
        const task = () => {
            console.log(`Hi! This is ${name}`);
            console.log('this', this);
            this.next();
        };
        this.tasks.push(task);
        setTimeout(() => {       // 把this.next()放到调用栈清空之后执行
            this.next();
        }, 0);
    };

    next() {
        const task = this.tasks.shift();  // 取第一个任务执行
        task && task();
    };

    sleep(time) {
        this._sleepWrapper(time, false);
        return this;   // 链式调用
    };

    sleepFirst(time) {
        this._sleepWrapper(time, true);
        return this;
    };

    _sleepWrapper(time,first) {
        const task = () => {
            setTimeout(() => {
                console.log(`Wake up after ${time}`);
                this.next();
            }, time * 1000);
        };

        if (first) {
            this.tasks.unshift(task);  // 放到任务队列
        } else {
            this.tasks.push(task);   // 放到任务队尾
        };
    };

    eat(type) {
        const task = () => {
            console.log(`Eat ${type}`);
            this.next();
        };
        this.tasks.push(task);   // 放到任务队
        return this;
    };
};

function LazyMan(name) {
    return new _LazyMan(name);
};


LazyMan('Hank');
LazyMan('Hank').sleep(10).eat('dinner');
LazyMan('Hank').eat('dinner').eat('supper');
LazyMan('Hank').sleepFirst(5).eat('supper');


